package org.reborn.demo

import org.reborn.engine.app._
import org.reborn.engine.render._

import scala.List

import org.reborn.engine.model.mesh.Mesh
import org.reborn.engine.model.mesh.MutableMesh
import org.reborn.engine.model.mesh.ImmutableMesh
import org.reborn.engine.model.mesh.VertexData
import org.reborn.engine.model.mesh.ImmutableVertexData
import org.reborn.engine.enums.ArrayType
import org.reborn.engine.enums.FaceMode
import org.reborn.engine.enums.UpdateFrequency

import org.reborn.utils.HeightMapUtil._
import org.reborn.engine.render.util._
import org.reborn.utils.Util._
import org.reborn.Constants._

import java.awt._
import java.awt.event._;

import javax.media.opengl._
import javax.media.opengl.GL
import javax.media.opengl.glu._
import com.jogamp.opengl.util._
import com.jogamp.opengl.util.awt.TextRenderer

object HeightMapVBOs extends GLApp {
  
  def main(args:Array[String]){
	
    val options = new GLAppOptions()
    options.title = "Heightmap VBO Test"
//    options.fullscreen = false
    options.debugGL = true
    
	HeightMapVBOs.startApp(options)
  }
  
  
  import GL._
  val hm = Scale(DiamondSquare(8,0.5f,0.0f,0.5f),0.0f,1.0f)
  val hm2 = Scale(DiamondSquare(8,0.0f,0.5f,0.5f),0.0f,1.0f)
  //val hm = DiamondSquare(8,0.0f,1.0f,0.45f)
  //val hm2 = DiamondSquare(8,0.0f,1.0f,0.45f)      
    
  var dt = 0.0f;
  var dRot = 0.0f
  val text = new TextRenderer(new Font("SansSerif", Font.BOLD, 20))
  
  var calced = false;
  
  var meshId = -1;
  var mesh:MutableMesh = null;
  
  var fpsAvg = 0.0f;
  
  override def initScene(drawable:GLAutoDrawable){
    val gl = drawable.getGL.getGL2
    import gl._
    
    //util.useMeshRendererIfAvailable(gl,RenderMeshVertexArrayRange)
    
    glEnable(GL_DEPTH_TEST)
    glDepthFunc(GL_LEQUAL)
    glHint(GL2ES1.GL_PERSPECTIVE_CORRECTION_HINT,GL_NICEST)
    glClearColor(0.3f,0.3f,0.3f,1.0f)
    
    val vertArray = new Array[Float](hm.length * hm.length * 3)
    val colArray = new Array[Float](hm.length * hm.length * 3)
    val faceArray = new Array[Int]((hm.length-1) * (hm.length-1) * 6)
    
    var curIndex = 0;
    var curPoly = 0;
    for(x <- 0 until hm.length;
        y <- 0 until hm.length){
          val fX = -.5f + (x.asInstanceOf[Float] / hm.length.asInstanceOf[Float]) //* 2.0f
          val fZ = -.5f + (y.asInstanceOf[Float] / hm.length.asInstanceOf[Float]) //* 2.0f
    
          vertArray(curIndex*3) = fX
          vertArray(curIndex*3+1) = 0.0f
          vertArray(curIndex*3+2) = fZ
          
          if(x < (hm.length -1) && y < (hm.length -1)){
            val leftBot = x * hm.length + y
            val rightBot = (x+1) * hm.length + y
            val rightTop = (x+1) * hm.length + y + 1
            val leftTop = x * hm.length + y + 1
            faceArray(curPoly) = leftBot
            faceArray(curPoly+1) = rightBot
            faceArray(curPoly+2) = rightTop
            faceArray(curPoly+3) = rightTop
            faceArray(curPoly+4) = leftTop
            faceArray(curPoly+5) = leftBot
            curPoly+=6;
          }

          curIndex = curIndex+1;
    }
    
    mesh = new MutableMesh(FaceMode.Triangle,faceArray.length / 3, 100)
    mesh.replaceFaceData(faceArray)
    mesh.replaceVertData(ArrayType.Vertex,3,vertArray)
    mesh.replaceVertData(ArrayType.Color,3,colArray)
    
    //var vertsData:List[ImmutableVertexData] = 
	//    	List(new ImmutableVertexData(ArrayType.Vertex,3,vertArray),
	//    		 new ImmutableVertexData(ArrayType.Color,3,colArray));
 	//mesh = new ImmutableMesh(vertsData,faceArray,FaceMode.Triangle)
	    
	meshId = util.meshRenderer.register(gl,mesh,UpdateFrequency.EachFrame)
  }
  
  override def updateLogic(seconds:Float){
    this.dt = seconds
    
    fpsAvg = ((25.0f * fpsAvg) + seconds) / 26.0f
    
    dRot = dRot + dt * 10.0f
    
    if(!calced){
	    val frame = (dRot*2.0f).asInstanceOf[Int]
	    
	    val xFac = (math.sin(dRot / 50.0f) * .5f).asInstanceOf[Float]
	    val xHm = Combine(hm,hm2){(f1,f2) => (f2 - f1) * xFac + f1 }

        val vertArray = mesh(ArrayType.Vertex).getDataArray
        val colArray = mesh(ArrayType.Color).getDataArray
     
	    var curIndex = 0;
	    for(x <- 0 until hm.length;
	        y <- 0 until hm.length){
	          val fY = xHm(x+frame,y+ frame/2,true) * 2.0f - 0.25f
	    
	          var cR = 0.0f
	          var cG = 0.0f
	          var cB = 0.0f
	          
	          if(fY<=0.2f)          { cR=0.5f; cG=0.5f; cB=1.0f}
	          if(fY>0.2f && fY<=.4) { cR=0.5f; cG=1.0f; cB=0.5f}
	          if(fY>0.4f && fY<=.6) { cR=1.0f; cG=1.0f; cB=0.5f}
	          if(fY>0.6f && fY<=.8) { cR=1.0f; cG=0.5f; cB=0.5f}
	          if(fY>.8)             { cR=1.0f; cG=1.0f; cB=1.0f}  
	          
	          vertArray(curIndex*3+1) = fY
	          
	          colArray(curIndex*3) = cR
	          colArray(curIndex*3+1) = cG
	          colArray(curIndex*3+2) = cB
	          
	          curIndex = curIndex+1;
	    }
     }
  }
  
  override def renderScene(drawable:GLAutoDrawable){
    val gl = drawable.getGL.getGL2
    import gl._
    
    dRot = dRot + dt * 10.0f
    
    glClear(GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT)
    glLoadIdentity();
    glTranslatef(0.0f,0.0f,-2.0f)
    
    glRotatef(50.0f,1.0f,0.0f,0.0f)
    //glRotatef(90.0f,1.0f,0.0f,0.0f)
    glRotatef(dRot*.1f,0.0f,1.0f,0.0f)

    glScalef(1.0f,0.5f,1.0f)
    glTranslatef(0.0f,-.5f,0.0f)
    glColor3f(1.0f,1.0f,1.0f)
    
    if(!calced){
      //var vertsData:List[ImmutableVertexData] = 
      //	List(new ImmutableVertexData(ArrayType.Vertex,3,vertArray),
      //		 new ImmutableVertexData(ArrayType.Color,3,colArray));
      //val mesh:ImmutableMesh = new ImmutableMesh(vertsData,faceArray,FaceMode.Triangle)
    
    
     //util.meshRenderer.update(gl,meshId,mesh)
     util.meshRenderer.updateArrayData(gl,meshId,mesh,ArrayType.Vertex)
     util.meshRenderer.updateArrayData(gl,meshId,mesh,ArrayType.Color)
     //calced = true
    }
    util.meshRenderer.render(gl,meshId)
    
    text beginRendering(drawable.getWidth, drawable.getHeight)
    text setColor(1.0f, 1.0f, 1.0f, 1.0f);
    text draw("" + 1.0f/dt,0,0);
    text draw("" + 1.0f/fpsAvg,0,16);
    text endRendering
      
    glFlush
  }
}